# -*- coding: utf-8 -*-
# FileName:     zmidi.py
# Time:         23/5/10 010 下午 8:48
# Author:       Zhou Hang
# Description:  I don't want to write.
import pygame.midi

# pygame.midi 手册
# https://www.pygame.org/docs/ref/midi.html#pygame.midi.init


class PygameMidi:
    _instance = None

    def __new__(cls, *args, **kw):
        """
        实现单例
        :param args:
        :param kw:
        """
        if cls._instance is None:
            cls._instance = object.__new__(cls, *args, **kw)
        return cls._instance

    def __init__(self, with_device: bool = False):
        self.input = None  # 如果with_device为真，该值会被初始化为midi输入设备
        pygame.midi.init()
        self.device_num = pygame.midi.get_count()
        self.devices = []
        for i in range(self.device_num):
            # get_device_info 仅仅返回tuple而已
            self.devices.append(pygame.midi.get_device_info(i))

    def open_device(self):
        self.init_device()

    def show(self):
        print(f"默认输入设备号: {pygame.midi.get_default_input_id()}")
        print(f"默认输出设备号: {pygame.midi.get_default_output_id()}")
        print("PS: 默认设备号可以通过环境变量修改")
        print(f"设备总数: {self.device_num}")
        print(f"设备信息总览:")
        for i, device in enumerate(self.devices):
            print(f"{i}: interf:{device[0].decode('utf-8')} "
                  f"name={device[1].decode('utf-8')} "
                  f"isInput:{bool(device[2])} "
                  f"isOutput:{bool(device[3])} "
                  f"isOpened:{bool(device[4])} "
                  )

    def get_device_id(self):
        # 这里我使用名称为WORLDE easy key的设备. 按照名字寻找是因为我不知道不同系统下这个设别号会不会变化
        for i, device in enumerate(self.devices):
            if device[1].decode('utf-8').startswith('WORLDE'):
                if bool(device[2]):  # 是Input设备
                    return i  # 返回设备id
        raise RuntimeError("未找到合适的midi输入设备，请检查设备是否插入")

    def init_device(self):
        self.input = pygame.midi.Input(self.get_device_id(), buffer_size=3)

    def poll(self):
        return self.input.poll()

    def read(self, buffer_size):
        # TODO: 这里如果同时按下一百个按键会报错Exception: b'PortMidi: Buffer overflow'
        return self.input.read(buffer_size)

    def close(self):
        pygame.midi.quit()

    @staticmethod
    def get_frequency(note: int):
        return pygame.midi.midi_to_frequency(note)


def main():
    pmidi = PygameMidi()
    pmidi.open_device()
    # pmidi.show()


if __name__ == "__main__":
    main()
